package com.tebiecloud.order.server.controller;

import cn.hutool.db.sql.Order;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.tebiecloud.act.client.model.entity.Act;
import com.tebiecloud.act.client.model.entity.ActGiftPack;
import com.tebiecloud.act.client.model.entity.ActGoodsRef;
import com.tebiecloud.base.client.constants.BaseConstants;
import com.tebiecloud.base.client.model.entity.BaseAccount;
import com.tebiecloud.base.client.service.IBaseUserServiceClient;
import com.tebiecloud.common.constants.ResultEnum;
import com.tebiecloud.common.constants.UserConstants;
import com.tebiecloud.common.model.PageResult;
import com.tebiecloud.common.security.SecurityHelper;
import com.tebiecloud.common.security.SecurityUserDetails;
import com.tebiecloud.common.utils.*;
import com.tebiecloud.goods.client.model.entity.Goods;
import com.tebiecloud.goods.client.model.entity.GoodsSpecification;
import com.tebiecloud.mpweixin.client.model.entity.MpweixinUser;
import com.tebiecloud.mpweixin.client.model.entity.MpweixinUserExpand;
import com.tebiecloud.mpweixin.client.model.mpweixin.*;
import com.tebiecloud.order.client.constatns.OrderConstants;
import com.tebiecloud.order.client.model.entity.*;
import com.tebiecloud.order.client.model.vo.*;
import com.tebiecloud.order.server.properties.OrderProperties;
import com.tebiecloud.order.server.service.*;
import com.tebiecloud.common.model.PageParams;
import com.tebiecloud.common.model.ResultBody;
import com.tebiecloud.order.server.service.feign.*;
import com.tebiecloud.order.server.utils.SequenceUtils;
import com.tebiecloud.store.client.model.entity.Store;
import com.tebiecloud.store.client.model.entity.StoreStaff;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RestController;

import java.net.URLEncoder;
import java.util.*;

/**
 * 预约单 前端控制器
 *
 * @author tebie
 * @date 2019-10-28
 */
@Slf4j
@RestController
@RequestMapping("/reserve")
public class ReserveController {

    @Autowired
    private OrderProperties orderProperties;

    @Autowired
    private ReserveService reserveService;

    @Autowired
    private ReserveGoodsService reserveGoodsService;

    @Autowired
    private ReserveOrderService reserveOrderService;

    @Autowired
    private GoodsServiceClient goodsServiceClient;

    @Autowired
    private GoodsSpecificationServiceClient goodsSpecificationServiceClient;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private MpweixinServiceClient mpweixinServiceClient;

    @Autowired
    private ActServiceClient actServiceClient;

    @Autowired
    private ActGoodsRefServiceClient actGoodsRefServiceClient;

    @Autowired
    private StoreServiceClient storeServiceClient;

    @Autowired
    private StoreStaffServiceClient storeStaffServiceClient;

    @Autowired
    private OrderEvaluateService orderEvaluateService;

    @Autowired
    private MpweixinApiServiceClient mpweixinApiServiceClient;

    @Autowired
    private BaseUserServiceClient baseUserServiceClient;

    @Autowired
    private OrderrService orderrService;

    /**
     * 创建预约
     *
     * @param receiver    预约人名称,
     * @param trolleyList 头像,
     * @param phone       手机号码
     * @return
     */
    @PostMapping("create")
    public ResultBody create(
            @RequestParam(value = "actId", required = false) Long actId,
            @RequestParam(value = "receiver", required = false) String receiver,
            @RequestParam(value = "phone", required = false) String phone,
            @RequestParam(value = "trolleyList", required = false) String trolleyList) {
        SecurityUserDetails securityUserDetails = SecurityHelper.getUser();
        long userId = securityUserDetails.getUserId();
        List<GoodsSpecList> goodsSpecListList = getGoodsSpecList(actId, trolleyList);
        if (goodsSpecListList == null) {
            return ResultBodyUtils.failedMsg("查询规格不存在");
        }
        String today = DateUtils.formatDate(new Date(), "yyyyMMdd");
        //先校验有无预约存在服务中
        List<Long> oldStatusList = Lists.newArrayList();
        oldStatusList.add(1L);
        oldStatusList.add(2L);
        oldStatusList.add(3L);
        oldStatusList.add(4L);
        QueryWrapper<Reserve> oldReserveQueryWrapper = new QueryWrapper<>();
        oldReserveQueryWrapper.eq("user_id", userId);
        oldReserveQueryWrapper.eq("store_id", goodsSpecListList.get(0).getStoreId());
        oldReserveQueryWrapper.in("status", oldStatusList);
        List<Reserve> oldReserveList = reserveService.list(oldReserveQueryWrapper);
        if (oldReserveList != null && oldReserveList.size() > 0) {
            return ResultBodyUtils.failedMsg("您已经有排号在进行。");
        }
        /**
         * 获取编号
         */
        int time = 5;
        String lockkey = OrderConstants.REDIS_RESERVER_NUMBER_ + goodsSpecListList.get(0).getStoreId() + today;
        boolean isLock = redisUtils.lock(lockkey, time);
        if (!isLock) {
            throw new RuntimeException("编号资源被占用");
        }
        String key = OrderConstants.STORE_RESERVER_NUMBER_ + goodsSpecListList.get(0).getStoreId() + today;
        String numStr = redisUtils.get(key);
        long num = 0L;
        if (numStr == null) {
            num = 1L;
            redisUtils.set(key, "2", DateUtils.getRemainSecondsOneDay(new Date()));
        } else {
            num = Long.valueOf(numStr);
            redisUtils.incr(key, 1);
        }
        redisUtils.unLock(lockkey);

        //获取openid
        MpweixinUserExpand mpweixinUserExpand = null;
        if (BaseConstants.ACCOUNT_DOMAIN_MP.equals(securityUserDetails.getDomain())) {
            String[] username = securityUserDetails.getUsername().split(":");
            if (username.length >= 2) {
                //获取用户信息
                ResultBody<MpweixinUserExpand> mpweixinUserExpandResultBody = mpweixinServiceClient.selectUserInfo(userId, username[1]);
                if (mpweixinUserExpandResultBody != null && mpweixinUserExpandResultBody.getCode() == ResultEnum.OK.getCode()) {
                    mpweixinUserExpand = mpweixinUserExpandResultBody.getData();
                }
            }
        }
        String number = SequenceUtils.getSequence(num);
        Reserve reserve = new Reserve();
        reserve.setNumber(number);
        reserve.setActId(actId);
        reserve.setUserId(userId);
        reserve.setStoreId(goodsSpecListList.get(0).getStoreId());
        reserve.setReceiver(receiver);
        if (mpweixinUserExpand != null) {
            reserve.setReceiverHeadimgurl(mpweixinUserExpand.getHeadimgurl() == null ? UserConstants.headImageUrl : mpweixinUserExpand.getHeadimgurl());
        }
        reserve.setPhone(phone);
        reserve.setStatus(1);
        if (reserveService.save(reserve)) {
            saveBatchReserveGoods(reserve.getReserveId(), goodsSpecListList);
        }
        //查询前面还有多少人排号
        Map<String, Integer> reultMap = getRemain(reserve);
        //通知门店排号
        reserveService.noticeReserve(reserve.getStoreId());
        return ResultBodyUtils.ok(reultMap);
    }

    /**
     * 查询还需等待多少
     *
     * @return
     */
    private Map<String, Integer> getRemain(Reserve reserve) {
        Map<String, Integer> reultMap = Maps.newHashMap();
        List<Long> statusList = Lists.newArrayList();
        statusList.add(1L);
        statusList.add(2L);
        statusList.add(3L);
        statusList.add(4L);
        QueryWrapper<Reserve> reserveQueryWrapper = new QueryWrapper<>();
        reserveQueryWrapper.eq("store_id", reserve.getStoreId());
        reserveQueryWrapper.lt("ct", reserve.getCt());
        reserveQueryWrapper.in("status", statusList);
        List<Reserve> reserveList = reserveService.list(reserveQueryWrapper);
        Map<String, Object> resultMap = Maps.newHashMap();
        int serviceWaitNumber = 0;//服务人数
        int serviceWaitTime = 0;//服务时长：单位：分钟
        if (reserveList != null && reserveList.size() > 0) {
            serviceWaitNumber = reserveList.size();
            for (Reserve reserve1 : reserveList) {
                List<ReserveGoods> reserveGoodsList = getReserveGoodsList(reserve1);
                if (reserveGoodsList != null && reserveGoodsList.size() > 0) {
                    for (ReserveGoods reserveGoods : reserveGoodsList) {
                        long currentTime = System.currentTimeMillis();//当前时间
                        Long remainTime = 0L;//剩余时间
                        if (reserve1.getStatus() == 3 || reserve1.getStatus() == 4) {
                            //计算可能剩余多少分钟
                            if (reserve1.getStartTime() != null) {
                                long differentTime = currentTime - reserve1.getStartTime().getTime();
                                log.info(">>minjie 服务id：{},已经开始服务多少时间：{}毫秒", reserve1.getReserveId(), differentTime);
                                if (reserveGoods.getServiceTime() != null) {
                                    if (reserveGoods.getServiceTime() * 60 * 1000 - differentTime > 0) {
                                        remainTime = (reserveGoods.getServiceTime() * 60 * 1000 - differentTime) / (1000 * 60);
                                    }
                                }
                                log.info(">>minjie 服务id：{},剩余多少时间：{}分钟", reserve1.getReserveId(), remainTime);
                            }
                            serviceWaitTime = serviceWaitTime + remainTime.intValue();
                        } else {
                            serviceWaitTime = serviceWaitTime + reserveGoods.getServiceTime();
                        }
                    }
                }
            }
            //如果服务中小于坑数
            if (serviceWaitNumber < OrderConstants.RESERVE_NUM) {
                serviceWaitTime = 0;
            }
        }
        reultMap.put("serviceWaitNumber", serviceWaitNumber);
        reultMap.put("serviceWaitTime", serviceWaitTime);
        return reultMap;
    }

    /**
     * 获取预约服务信息
     *
     * @param reserve
     * @return
     */
    private List<ReserveGoods> getReserveGoodsList(Reserve reserve) {
        QueryWrapper<ReserveGoods> reserveGoodsQueryWrapper = new QueryWrapper<>();
        reserveGoodsQueryWrapper.eq("reserve_id", reserve.getReserveId());
        List<ReserveGoods> reserveGoodsList = reserveGoodsService.list(reserveGoodsQueryWrapper);
        return reserveGoodsList;
    }

    /**
     * 获取商品规格列表
     *
     * @param trolleyList
     * @return
     */
    private List<GoodsSpecList> getGoodsSpecList(Long actId, String trolleyList) {
        if (StringUtils.isEmpty(trolleyList)) return null;
        //字符串转对象列表
        JSONArray jsonArray = JSONArray.parseArray(trolleyList);
        List<TrolleyList> trolleyLists = jsonArray.toJavaList(TrolleyList.class);
        // 获取活动信息
        List<GoodsSpecList> goodsSpecListList = new ArrayList<>();
        if (actId == null || actId == 0) {
            //普通商品
            for (TrolleyList trolleyList1 : trolleyLists) {
                ResultBody<GoodsSpecification> goodsSpecificationResultBody = goodsSpecificationServiceClient.infoGoodsSpecification(trolleyList1.getGoodsSpecificationId());
                if (goodsSpecificationResultBody != null && goodsSpecificationResultBody.getCode() == ResultEnum.OK.getCode()) {
                    GoodsSpecification goodsSpecification = goodsSpecificationResultBody.getData();
                    GoodsSpecList goodsSpecList = new GoodsSpecList();
                    goodsSpecList.setGoodsId(goodsSpecification.getGoodsId());
                    goodsSpecList.setAmount(trolleyList1.getAmount());
                    goodsSpecList.setPrice(goodsSpecification.getPrice());
                    goodsSpecList.setSpecId(goodsSpecification.getSpecId());
                    goodsSpecList.setSpecName(goodsSpecification.getName());
                    goodsSpecList.setServiceTime(goodsSpecification.getServiceTime());
                    //计算获利=销售价*佣金比例*数量
                    Double profit = goodsSpecification.getPrice() * (Double.valueOf(goodsSpecification.getCommissionRate()) / 100) * trolleyList1.getAmount();
                    goodsSpecList.setProfit(profit.intValue());
                    goodsSpecList.setCoin(goodsSpecification.getCoin());
                    //查询商品信息
                    ResultBody<List<Goods>> goodsResult = goodsServiceClient.selectByGoodsIds(goodsSpecification.getGoodsId().toString());
                    if (goodsResult != null && goodsResult.getCode() == ResultEnum.OK.getCode()) {
                        List<Goods> goodsList = goodsResult.getData();
                        if (goodsList.size() > 0) {
                            goodsSpecList.setStoreId(goodsList.get(0).getStoreId());
                            goodsSpecList.setGoodsName(goodsList.get(0).getName());
                            goodsSpecList.setGoodsPic(goodsList.get(0).getSharePic());//使用正方形的图
                            goodsSpecList.setDesc(goodsList.get(0).getDes());//设置使用规格
                        }
                    }
                    goodsSpecListList.add(goodsSpecList);
                }
            }
        } else {
            Act act = null;
            //查询活动信息
            ResultBody<Act> actResultBody = actServiceClient.selectActByActId(actId);
            if (actResultBody != null && actResultBody.getCode() == ResultEnum.OK.getCode()) {
                act = actResultBody.getData();
                if (act == null) return null;
            } else {
                return null;
            }
            ActGiftPack actGiftPack = null;
            if (act.getActType() == 2) {//如果是体验活动
                ResultBody<ActGiftPack> actGiftPackResultBody = actServiceClient.selectActGift(actId);
                if (actGiftPackResultBody != null && actGiftPackResultBody.getCode() == ResultEnum.OK.getCode()) {
                    actGiftPack = actGiftPackResultBody.getData();
                    if (actGiftPack == null) return null;
                } else {
                    return null;
                }
            }
            //活动商品
            for (TrolleyList trolleyList1 : trolleyLists) {
                //查询活动规格信息
                ResultBody<List<ActGoodsRef>> actGoodsRefResultBody = actGoodsRefServiceClient.listActGoodsRef(actId, trolleyList1.getGoodsSpecificationId());
                if (actGoodsRefResultBody != null && actGoodsRefResultBody.getCode() == ResultEnum.OK.getCode()) {
                    List<ActGoodsRef> actGoodsRefList = actGoodsRefResultBody.getData();
                    GoodsSpecList goodsSpecList = new GoodsSpecList();
                    if (actGoodsRefList.size() > 0) {
                        goodsSpecList.setGoodsId(actGoodsRefList.get(0).getGoodsId());
                        goodsSpecList.setAmount(trolleyList1.getAmount());
                        goodsSpecList.setSpecId(actGoodsRefList.get(0).getSpecId());
                        if (actGiftPack == null) {//限时促销活动计算
                            //计算获利=销售价*佣金比例*数量
                            Double profit = actGoodsRefList.get(0).getPrice() * (Double.valueOf(actGoodsRefList.get(0).getCommissionRate()) / 100) * trolleyList1.getAmount();
                            goodsSpecList.setProfit(profit.intValue());
                            goodsSpecList.setPrice(actGoodsRefList.get(0).getPrice());
                        } else if (actGiftPack != null) {//体验活动
                            //计算获利=销售价*佣金比例*数量
                            Double profit = actGiftPack.getPrice() * (Double.valueOf(actGiftPack.getCommissionRate()) / 100) * trolleyList1.getAmount();
                            goodsSpecList.setProfit(profit.intValue());
                            goodsSpecList.setPrice(actGiftPack.getPrice());
                        }
                        //查询商品信息
                        ResultBody<List<Goods>> goodsResult = goodsServiceClient.selectByGoodsIds(actGoodsRefList.get(0).getGoodsId().toString());
                        if (goodsResult != null && goodsResult.getCode() == ResultEnum.OK.getCode()) {
                            List<Goods> goodsList = goodsResult.getData();
                            if (goodsList.size() > 0) {
                                goodsSpecList.setStoreId(goodsList.get(0).getStoreId());
                                goodsSpecList.setGoodsName(goodsList.get(0).getName());
                                goodsSpecList.setGoodsPic(goodsList.get(0).getSharePic());//使用正方形的图
                            }
                        }
                        //查询规格信息
                        ResultBody<GoodsSpecification> goodsSpecificationResultBody = goodsSpecificationServiceClient.infoGoodsSpecification(trolleyList1.getGoodsSpecificationId());
                        if (goodsSpecificationResultBody != null && goodsSpecificationResultBody.getCode() == ResultEnum.OK.getCode()) {
                            GoodsSpecification goodsSpecification = goodsSpecificationResultBody.getData();
                            goodsSpecList.setSpecName(goodsSpecification.getName());
                            goodsSpecList.setServiceTime(goodsSpecification.getServiceTime());
                        }
                    }
                    goodsSpecListList.add(goodsSpecList);
                }
            }
        }
        return goodsSpecListList;
    }

    /**
     * 批量保存预约商品信息
     *
     * @param reserveId
     * @param goodsSpecListList
     * @return
     */
    private List<ReserveGoods> saveBatchReserveGoods(long reserveId, List<GoodsSpecList> goodsSpecListList) {
        List<ReserveGoods> reserveGoodsList = Lists.newArrayList();
        if (goodsSpecListList == null) {
            return reserveGoodsList;
        }
        for (GoodsSpecList goodsSpecList : goodsSpecListList) {
            ReserveGoods reserveGoods = new ReserveGoods();
            reserveGoods.setAmount(goodsSpecList.getAmount());
            reserveGoods.setGoodsId(goodsSpecList.getGoodsId());
            reserveGoods.setGoodsName(goodsSpecList.getGoodsName());
            reserveGoods.setGoodsPic(goodsSpecList.getGoodsPic());
            reserveGoods.setGoodsPrice(goodsSpecList.getPrice());
            reserveGoods.setGoodsSpecificationId(goodsSpecList.getSpecId());
            reserveGoods.setReserveId(reserveId);
            reserveGoods.setServiceTime(goodsSpecList.getServiceTime());
            reserveGoods.setSpecificationName(goodsSpecList.getSpecName());
            reserveGoods.setStoreId(goodsSpecList.getStoreId());
            reserveGoods.setTotalPrice(goodsSpecList.getPrice() * goodsSpecList.getAmount());
            reserveGoodsList.add(reserveGoods);
        }
        reserveGoodsService.saveBatch(reserveGoodsList);
        return reserveGoodsList;
    }

    /**
     * 查看是否支付成功
     *
     * @param reserveId
     * @return
     */
    @PostMapping(value = "getreserveorder")
    public ResultBody getReserveOrder(@RequestParam(value = "reserveId") long reserveId) {
        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("isPay", 0);//是否支付成功：0否，1是
        resultMap.put("orderId", 0);//订单id
        //查看是否有订单
        QueryWrapper<ReserveOrder> reserveOrderQueryWrapper = new QueryWrapper<>();
        reserveOrderQueryWrapper.eq("reserve_id", reserveId);
        reserveOrderQueryWrapper.orderByDesc("ct");
        reserveOrderQueryWrapper.last("LIMIT 1");
        ReserveOrder reserveOrder = reserveOrderService.getOne(reserveOrderQueryWrapper);
        if (reserveOrder == null) return ResultBodyUtils.ok(resultMap);
        //查看订单是否支付
        QueryWrapper<Orderr> orderrQueryWrapper = new QueryWrapper<>();
        orderrQueryWrapper.eq("order_id", reserveOrder.getOrderId());
        Orderr orderr = orderrService.getOne(orderrQueryWrapper);
        if (orderr == null) return ResultBodyUtils.ok(resultMap);
        if (orderr.getStatus().equals(OrderConstants.ORDER_STATUS_COMPLETED)) {
            resultMap.put("isPay", 1);//是否支付成功：0否，1是
            resultMap.put("orderId", orderr.getOrderId());//订单id
            return ResultBodyUtils.ok(resultMap);
        }
        return ResultBodyUtils.ok(resultMap);
    }

    /**
     * 查询预约列别
     */
    @PostMapping("/liststore")
    public ResultBody listStore(@RequestParam(value = "page", defaultValue = "1") int page,
                                @RequestParam(value = "limit", defaultValue = "10") int limit,
                                @RequestParam("storeId") Long storeId) {
        QueryWrapper<Reserve> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("store_id", storeId);
        IPage<Reserve> page1 = reserveService.page(new Page<>(page, limit), queryWrapper);
        if (page1.getTotal() == 0) return ResultBodyUtils.failed("店铺没有预约订单");
        return ResultBodyUtils.ok(page1);
    }

    /**
     * 获取预约列表
     *
     * @param page
     * @param limit
     * @param storeId//门店的预约
     * @param status//状态：-1全部，1排队中，4服务中，5已完成，6取消或者已过期
     * @param lng
     * @param lat
     * @return
     */
    @PostMapping(value = "list")
    public ResultBody list(
            @RequestParam(value = "page", defaultValue = "1") int page,
            @RequestParam(value = "limit", defaultValue = "10") int limit,
            @RequestParam(value = "storeId", required = false) Long storeId,
            @RequestParam(value = "status", required = false, defaultValue = "-1") int status,
            @RequestParam(value = "lng", required = false) Double lng,
            @RequestParam(value = "lat", required = false) Double lat) {
        SecurityUserDetails securityUserDetails = SecurityHelper.getUser();
        long currentUserId = securityUserDetails.getUserId();
        QueryWrapper<Reserve> queryWrapper = new QueryWrapper();
        if (BaseConstants.ACCOUNT_DOMAIN_MP.equals(securityUserDetails.getDomain())) {
            //个人查看自己的预约排号
            queryWrapper.eq("user_id", currentUserId);
            queryWrapper.orderByDesc("ct");
        }
        if (storeId != null) queryWrapper.eq("store_id", storeId);
        if (status != -1) {
            List<Long> statusList = Lists.newArrayList();
            if (status == 1) {
                statusList.add(1L);
                statusList.add(2L);
                queryWrapper.in("status", statusList);
                if (BaseConstants.ACCOUNT_DOMAIN_USER.equals(securityUserDetails.getDomain())) {
                    queryWrapper.orderByDesc("ct");
                }
            }
            if (status == 4) {
                statusList.add(2L);
                statusList.add(3L);
                statusList.add(4L);
                queryWrapper.in("status", statusList);
                if (BaseConstants.ACCOUNT_DOMAIN_USER.equals(securityUserDetails.getDomain())) {
                    queryWrapper.orderByAsc("number");
                }
            }
            if (status == 5) {
                queryWrapper.eq("status", status);
                if (BaseConstants.ACCOUNT_DOMAIN_USER.equals(securityUserDetails.getDomain())) {
                    queryWrapper.orderByDesc("ct");
                }
            }
            if (status == 6) {
                statusList.add(0L);
                statusList.add(6L);
                queryWrapper.in("status", statusList);
                if (BaseConstants.ACCOUNT_DOMAIN_USER.equals(securityUserDetails.getDomain())) {
                    queryWrapper.orderByDesc("ct");
                }
            }
        }
        IPage<Reserve> reserveIPage = reserveService.page(new PageParams(page, limit), queryWrapper);
        PageResult<ReserveList> reserveListPageResult = new PageResult<>(reserveIPage);
        if (reserveIPage.getRecords() != null && reserveIPage.getRecords().size() > 0) {
            List<ReserveList> reserveLists = Lists.newArrayList();
            for (Reserve reserve : reserveIPage.getRecords()) {
                ReserveList reserveList = BeanConvertUtils.convertBean(reserve, ReserveList.class);
                //计算过去多少分钟
                Long before = DateUtils.getBeforeMinutes(reserve.getCt());
                reserveList.setBeforeTime(before.intValue());
                //B端查看排队
                if (BaseConstants.ACCOUNT_DOMAIN_USER.equalsIgnoreCase(securityUserDetails.getDomain())) {
                    if (reserve.getStaffId() != null && reserve.getStaffId() == currentUserId) {
                        reserveList.setIsMyReserve(1);
                    } else {
                        reserveList.setIsMyReserve(0);
                    }
                } else {
                    reserveList.setIsMyReserve(0);
                }
                //查询门店
                ResultBody<Store> storeResultBody = storeServiceClient.getStore(reserveList.getStoreId());
                if (storeResultBody != null && storeResultBody.getCode() == ResultEnum.OK.getCode()) {
                    Store store = storeResultBody.getData();
                    if (store != null && lng != null && lat != null) {
                        String distance = DistanceUtils.getDistance(lng, lat, store.getLng(), store.getLat());
                        reserveList.setDistance(distance);
                    }
                    reserveList.setStoreName(store.getName());
                }
                //查询员工
                if (reserveList.getStaffId() != null) {
                    ResultBody<StoreStaff> storeStaffResultBody = storeStaffServiceClient.selectStoreStaff(reserveList.getStoreId(), reserveList.getStaffId(), null);
                    if (storeStaffResultBody != null && storeStaffResultBody.getCode() == ResultEnum.OK.getCode()) {
                        StoreStaff storeStaff = storeStaffResultBody.getData();
                        reserveList.setStaffName(storeStaff.getName());
                    }
                }
                //查询订单
                QueryWrapper<ReserveOrder> reserveOrderQueryWrapper = new QueryWrapper<>();
                reserveOrderQueryWrapper.eq("reserve_id", reserve.getReserveId());
                reserveOrderQueryWrapper.orderByDesc("ct");
                reserveOrderQueryWrapper.last(" LIMIT 1");
                ReserveOrder reserveOrder = reserveOrderService.getOne(reserveOrderQueryWrapper);
                if (reserveOrder != null) {
                    reserveList.setOrderId(reserveOrder.getOrderId());
                    //查看是否已经评价
                    QueryWrapper<OrderEvaluate> orderEvaluateQueryWrapper = new QueryWrapper<>();
                    orderEvaluateQueryWrapper.eq("order_id", reserveOrder.getOrderId());
                    orderEvaluateQueryWrapper.last("LIMIT 1");
                    OrderEvaluate orderEvaluate = orderEvaluateService.getOne(orderEvaluateQueryWrapper);
                    if (orderEvaluate != null) {
                        reserveList.setIsEvaluate(1);
                    } else {
                        reserveList.setIsEvaluate(0);
                    }
                    reserveList.setCt(reserveOrder.getCt());
                }
                //查询前面排队还有多少人
                Map<String, Integer> reultMap = getRemain(reserve);
                reserveList.setServiceWaitNumber(reultMap.get("serviceWaitNumber"));
                reserveList.setServiceWaitTime(reultMap.get("serviceWaitTime"));
                //获取规格列表
                QueryWrapper<ReserveGoods> reserveGoodsQueryWrapper = new QueryWrapper<>();
                reserveGoodsQueryWrapper.eq("reserve_id", reserve.getReserveId());
                List<ReserveGoods> reserveGoodsList = reserveGoodsService.list(reserveGoodsQueryWrapper);
                reserveList.setReserveGoodsList(reserveGoodsList);
                reserveLists.add(reserveList);
            }
            reserveListPageResult.setRecords(reserveLists);
        }
        //加上额外属性
        reserveListPageResult.setAttr(String.valueOf(status));
        return ResultBodyUtils.ok(reserveListPageResult);
    }

    /**
     * 更新状态
     *
     * @param reserveId
     * @param status    状态：0取消，2开始服务，3完成服务
     * @return
     */
    @PostMapping("update")
    public ResultBody update(@RequestParam("reserveId") long reserveId,
                             @RequestParam("status") int status) {
        QueryWrapper<Reserve> reserveQueryWrapper = new QueryWrapper<>();
        reserveQueryWrapper.eq("reserve_id", reserveId);
        Reserve reserve = reserveService.getOne(reserveQueryWrapper);
        if (reserve == null) return ResultBodyUtils.failedMsg("查询不存在");
        SecurityUserDetails securityUserDetails = SecurityHelper.getUser();
        long userId = securityUserDetails.getUserId();
        if (reserve.getStatus() != status) {
            Reserve newReserve = new ReserveList();
            newReserve.setReserveId(reserveId);
            //取消排队
            if (reserve.getStatus() == 1 && status == 0) {
                newReserve.setStatus(status);
                newReserve.setShutTime(new Date());
                reserveService.updateById(newReserve);
                return ResultBodyUtils.ok(newReserve);
            }
            //开始服务
            if (reserve.getStatus() == 2 && status == 3) {
                //查询有接服务
                List<Reserve> reserveList = getStaffReserve(reserve.getStoreId(), userId);
                if (reserveList != null && reserveList.size() > 0) {
                    return ResultBodyUtils.failedMsg("您已经接有单进行服务");
                }
                newReserve.setStatus(status);
                newReserve.setStartTime(new Date());
                //指定谁接的服务
                newReserve.setStaffId(securityUserDetails.getUserId());
                reserveService.updateById(newReserve);
                return ResultBodyUtils.ok(newReserve);
            }
            //完成服务（待支付）
            if (reserve.getStatus() == 3 && status == 4) {
                newReserve.setStatus(status);
                reserveService.updateById(newReserve);
                return ResultBodyUtils.ok(newReserve);
            }
        }
        return ResultBodyUtils.failedMsg("状态不正确");
    }

    /**
     * 查询是否已经接有单
     *
     * @param storeId
     * @param userId
     * @return
     */
    private List<Reserve> getStaffReserve(long storeId, long userId) {
        QueryWrapper<Reserve> reserveQueryWrapper = new QueryWrapper<>();
        reserveQueryWrapper.eq("store_id", storeId);
        reserveQueryWrapper.eq("staff_id", userId);
        reserveQueryWrapper.eq("status", 3);
        List<Reserve> reserveList = reserveService.list(reserveQueryWrapper);
        return reserveList;
    }

    /**
     * 获取微信图文消息
     *
     * @param reserveId
     * @return
     */
    @PostMapping("infompnews")
    public ResultBody infoMpNews(@RequestParam("reserveId") long reserveId) {
        Reserve reserve = reserveService.getById(reserveId);
        if (reserve == null) {
            log.info("xiaoc>> 排队取号信息不存在，reserveId: {}", reserveId);
            return ResultBodyUtils.failedMsg("信息不存在");
        }

        ResultBody<BaseAccount> resBaseAccount = baseUserServiceClient.getBaseAccountByUserId(reserve.getUserId());
        if (resBaseAccount == null || resBaseAccount.getCode() != ResultEnum.OK.getCode()) {
            log.info("xiaoc>> 用户信息不存在，reserve: {}", JsonUtils.Obj2Str(reserve));
            return ResultBodyUtils.failedMsg("用户信息不存在");
        }
        String account = resBaseAccount.getData().getAccount();
        if (!account.contains(":")) {
            log.info("xiaoc>> 账号不符合公众号规则，resBaseAccount: {}", JsonUtils.Obj2Str(resBaseAccount));
            return ResultBodyUtils.failedMsg("用户信息不存在");
        }

        // 推送订单信息
        SendMpMsgInfo sendMpMsgInfo = new SendMpMsgInfo();
        sendMpMsgInfo.setTouser(account.split(":")[1]);
        sendMpMsgInfo.setMsgtype("news");
        News news = new News();
        Article article = new Article();
        article.setDescription("");
        article.setTitle(orderProperties.getReserveNewsTitle());
        article.setUrl(orderProperties.getReserveNewsUrl() + "=" + reserveId);
        article.setPicurl(orderProperties.getReserveNewsPicurl());
        List<Article> articles = Lists.newArrayList();
        articles.add(article);
        news.setArticles(articles);
        sendMpMsgInfo.setNews(news);

        mpweixinApiServiceClient.sendMpMsg(JsonUtils.Obj2Str(sendMpMsgInfo));

        return ResultBodyUtils.ok();
    }

    /**
     * 获取预约单对应的二维码
     *
     * @param reserveId
     * @return
     */
    @PostMapping("infoqrcode")
    public ResultBody infoQrcode(@RequestParam("reserveId") long reserveId) {
        // 获取订单信息
        Reserve reserve = reserveService.getById(reserveId);
        if (reserve == null) {
            log.error("xiaoc>> 获取预约详情失败，reserveId: {}", reserveId);
            ResultBodyUtils.failed("预约不存在");
        }

        String reserveQrcodeStr = redisUtils.get(OrderConstants.REDIS_RESERVE_QRCODE_ + reserveId);
        ReserveQrcode reserveQrcode = JsonUtils.str2Bean(reserveQrcodeStr, ReserveQrcode.class);
        if (reserveQrcode == null) {
            // 获取二维码链接
            QrcodeParam qrcodeParam = new QrcodeParam();
            qrcodeParam.setExpire_seconds(3 * 24 * 60 * 60); // 有效时间，单位秒
            qrcodeParam.setAction_name("QR_STR_SCENE"); // 临时字符串参数
            ActionInfo actionInfo = new ActionInfo();
            Scene scene = new Scene();
            scene.setScene_str(OrderConstants.RESERVE_QRCODE_SCENESTR_ + reserveId);
            actionInfo.setScene(scene);
            qrcodeParam.setAction_info(actionInfo);
            ResultBody<QrcodeTicket> respQrcodeTicket = mpweixinApiServiceClient.createQrcode(JsonUtils.Obj2Str(qrcodeParam));
            if (respQrcodeTicket.getCode() != ResultEnum.OK.getCode()) { // 获取生成二维失败
                return respQrcodeTicket;
            }
            QrcodeTicket qrcodeTicket = respQrcodeTicket.getData();

            reserveQrcode = new ReserveQrcode();
            reserveQrcode.setReserveId(reserveId);
            try {
                reserveQrcode.setQrcodeUrl(String.format("%s%s", "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=", URLEncoder.encode(qrcodeTicket.getTicket(), "UTF-8")));
            } catch (Exception e) {
                e.printStackTrace();
                log.info("xiaoc>> 对ticket进行encode异常，取消encode");
                reserveQrcode.setQrcodeUrl(String.format("%s%s", "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=", qrcodeTicket.getTicket()));
            }
            reserveQrcode.setQrcodeContent(qrcodeTicket.getUrl());

            // 预约商品信息
            QueryWrapper<ReserveGoods> queryWrapperReserveGoods = new QueryWrapper();
            queryWrapperReserveGoods.eq("reserve_id", reserveId);
            ReserveGoods reserveGoods = reserveGoodsService.getOne(queryWrapperReserveGoods, false);
            if (reserveGoods != null) {
                reserveQrcode.setPrice(reserveGoods.getTotalPrice());

                // 获取门店信息
                ResultBody<Store> respStore = storeServiceClient.getStore(reserveGoods.getStoreId());
                if (respStore.getCode() == ResultEnum.OK.getCode()) {
                    reserveQrcode.setStoreName(respStore.getData().getName());
                }
            }

            // 缓存至redis
            redisUtils.set(OrderConstants.REDIS_RESERVE_QRCODE_ + reserveId, JsonUtils.Obj2Str(reserveQrcode), 3 * 24 * 60 * 60);
        }

        return ResultBodyUtils.ok(reserveQrcode);
    }
}
